/*********************************************************************************
 *      Copyright:  (C) 2025 LingYun IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(28/03/25)
 *         Author:  Guo Wenxue <guowenxue@gmail.com>
 *      ChangeLog:  1, Release initial version on "28/03/25 21:04:39"
 *                 
 ********************************************************************************/

#include "main.h"
#include "struct.h"

#define PROG_VERSION     "1.0.0"
#define RPI_SN           "RPI00001"
#define DEF_LOG_FILE     "tlv_client.log"
#define DEF_ACK_TIMEOUT  2
#define DEF_RETRYTIMES   3

int main(int argc, char **argv)
{
	int                   rv = -1;
	int                   times;
	int                   daemon_run = 0;
	int                   ch;
	const char            *db = "tlv_client.db";
    time_t                time_now = 0;
	time_t                time_before = 0;
	int                   sampling;
	char				  buf[1024];
	char                  *logfile = "running_cli.log";
	char                  pid_file[64] = { 0 };

	data_t                data;
	socket_cli            sock;

	memset(&data, 0, sizeof(data));
	memset(&sock, 0, sizeof(sock));

	struct option        opts[] = {
    	{"ip", required_argument, NULL, 'i'},
		{"port", required_argument, NULL, 'p'},
		{"times",  required_argument,  0, 't'},
		{"daemon", no_argument, NULL, 'd'},
		{"sn", required_argument, NULL, 's'},
		{"help", no_argument, NULL, 'h'},
		{NULL, 0, NULL, 0}
	};

	while((ch = getopt_long(argc, argv, "i:p:t:ds:h", opts, NULL)) != -1)
	{
		switch(ch)
		{
			case 'i':
				strncpy(sock.host, optarg, sizeof(sock.host)-1);
				sock.host[sizeof(sock.host)-1] = '\0';
				break;
		
			case 'p':
				sock.port = atoi(optarg);
				break;
			
			case 't':
				times = atoi(optarg);
				break;
			
			case 'd':
				daemon_run = 1;
				break;
    
			case 's':
				strncpy(data.sn, optarg, sizeof(data.sn) - 1);
				data.sn[sizeof(data.sn) - 1] = '\0';
				break;

			case 'h':
				print_usage(argv[0]);
				return 0;
		}
	}

	if(!sock.host || !sock.port)
	{
		print_usage(argv[0]);
		return 0;
	}

	snprintf(pid_file, sizeof(pid_file), "/tmp/%s.pid", progname);

	if(logger_init(logfile, LOG_LEVEL_INFO) < 0)
	{
		fprintf(stderr, "Initial logger file '%s' failure\n",logfile,strerror(errno));
		log_error("Initial logger system failure\n");
		return -1;
	}

	signal(SIGINT, stop);
	signal(SIGTERM, stop);

	if(daemon_run)
	{
		daemon(0,0);
		log_info("Running daemon\n");
	}

	if( database_init(db) < 0)
	{
		log_error("数据库初始化失败\n");
		return 2;
	}

	while(! pro_stop)    /*循环，为0的时候执行，刚开始给pro_stop赋值为0*/
	{
		sampling = 0;    /* 没到采样时间*/
		time(&time_now);   /*获取当前时间并存到time_now中 */ 

		if((time_now - time_before) >= times)    /* 如果到了采样时间*/
		{
			log_info("time reached\n");
			rv = 0;
			temp = 0x1122;
			if( 0 == rv )
			{
				tm=localtime(&time_now);
				time_before = time_now;
				packtlv_msg(&tlv, RPI_SN, temp, tm);
				logger_dump(LOG_LEVEL_DEBUG, tlv.buf, tlv.len);

				tlv.flag = TLV_FLAG_TX | TLV_FLAG_DB;
			}
			else
			{
				log_error("DS18B20 get temperature failure\n");
			}
		}
       
		if(socket_check(&sock) < 0)   /*检测连接状态,函数连接返回0，断开返回-1 */
		{
			if(sock.sockfd > 0)         /*断开连接后sockfd本身值不变，但这个文件描述符已经不能用了，需要关闭 */
			{ 
				close(sock.sockfd);
				log_error("socket disconnected\n");
				dbg_print("Disconnect from the server.\n");
			}	
			
			if(socket_connect(&sock) < 0)   /*重新连接，连接失败返回-           2，成功返回sockfd的值*/                                    
			{
				if( sampling )    /*采了数据但是连接断开了*/
				{
					database_safe_insert(&sock, &data);
				}
				sleep(1);
				continue;
			}
		}

		if( sampling ) /* 检查连接状态的时候是连接的*/ 
		{
			rv = write(sock.sockfd, buf, strlen(buf));       /* 没断开就写到buf缓冲区 */
			if(rv < 0)      /* 发送失败了，可能断开连接了*/ 
			{
				log_error("Write to server by sockfd[%d] failure: %s\n",sock.sockfd, strerror(errno));
				close(sock.sockfd);
				database_safe_insert(&sock, &data);  /*向表中插入一条数据 */
				continue;
			}
			log_info("Write to server by sockfd[%d] successfully!\n",sock.sockfd);
		}		
			
		rv = database_check_write_delete(&sock, &data);   /* 查询数据库是否有数据 */ 
		if( rv == 1)  
		{
			log_warn("send a data successfully\n");   /*成功发送一条数据*/
		}
		else if(rv == 0)      /*数据库为空 */
		{
			log_info("send all data of table and clean table\n");
		}
		else if(rv == -2)      /*发送数据失败 */
		{
			log_error("send data failure\n");
		}
		else
		{
			dbg_print("Error\n");
			break;
		}
	}

	database_term();
	close(sock.sockfd);

	return 0;
}

void stop(int signum)
{
	(void)signum;
	pro_stop = 1;
}
